home *** CD-ROM | disk | FTP | other *** search
- /*
- * rpcspy 11/91
- *
- * release 0.9
- *
- * Matt Blaze
- * Copyright 1991 Matt Blaze.
- * May be freely reproduced for non-commerical use.
- * All other rights, including use for direct commerical advantage or
- * use in a commerical product, are reserved by the author.
- *
- * bug reports, etc -> mab@cs.princeton.edu
- *
- * This is the main module.
- * It is much too long and way too ugly.
- */
- #include<sys/types.h>
- #include<sys/socket.h>
- #include <rpc/rpc.h>
- #include<net/if.h>
- #include<netinet/in_systm.h>
- #include<netinet/in.h>
- #include<netinet/ip.h>
- #include<netinet/udp.h>
- #include<rpc/types.h>
- #include<sys/param.h>
- #include<sys/time.h>
- #include <sys/file.h>
- #include <sys/errno.h>
- #include <sys/ioctl.h>
-
- /* generic handle type. this SEEMS to work most places */
- #include <nfs/nfs.h>
- typedef struct {
- long val[2]; /* file system id type */
- } fsid_t;
- struct fhs {
- fsid_t f1;
- u_short f2;
- char f3[4];
- };
- /* stolen from lots of places */
- #define FHMAXDATA (NFS_FHSIZE - sizeof(struct fhs) + 4)
-
- typedef struct sfh {
- fsid_t fh_fsid;
- u_short fh_len;
- char fh_data[FHMAXDATA];
- }sfh;
- #define fhandle_t sfh
-
-
- #include <netdb.h>
- #include <stdio.h>
- #include <signal.h>
- #include <strings.h>
-
- #include "rpcspy.h"
-
- int die();
-
- /* defs for arg/reply procs */
- int call_nfs_null(),
- call_nfs_getattr(),
- call_nfs_setattr(),
- call_nfs_root(),
- call_nfs_lookup(),
- call_nfs_readlink(),
- call_nfs_read(),
- call_nfs_writecache(),
- call_nfs_write(),
- call_nfs_create(),
- call_nfs_remove(),
- call_nfs_rename(),
- call_nfs_link(),
- call_nfs_symlink(),
- call_nfs_mkdir(),
- call_nfs_rmdir(),
- call_nfs_readdir(),
- call_nfs_statfs(),
- repl_nfs_null(),
- repl_nfs_getattr(),
- repl_nfs_setattr(),
- repl_nfs_root(),
- repl_nfs_lookup(),
- repl_nfs_readlink(),
- repl_nfs_read(),
- repl_nfs_writecache(),
- repl_nfs_write(),
- repl_nfs_create(),
- repl_nfs_remove(),
- repl_nfs_rename(),
- repl_nfs_link(),
- repl_nfs_symlink(),
- repl_nfs_mkdir(),
- repl_nfs_rmdir(),
- repl_nfs_readdir(),
- repl_nfs_statfs(),
- emit_nfs_null(),
- emit_nfs_getattr(),
- emit_nfs_setattr(),
- emit_nfs_root(),
- emit_nfs_lookup(),
- emit_nfs_readlink(),
- emit_nfs_read(),
- emit_nfs_writecache(),
- emit_nfs_write(),
- emit_nfs_create(),
- emit_nfs_remove(),
- emit_nfs_rename(),
- emit_nfs_link(),
- emit_nfs_symlink(),
- emit_nfs_mkdir(),
- emit_nfs_rmdir(),
- emit_nfs_readdir(),
- emit_nfs_statfs();
-
-
- /* tables for the arg/reply procs */
-
- int (*nfs_call_proc[])() = {
- call_nfs_null, /* 0 */
- call_nfs_getattr, /* 1 */
- call_nfs_setattr, /* 2 */
- call_nfs_root, /* 3 */
- call_nfs_lookup, /* 4 */
- call_nfs_readlink, /* 5 */
- call_nfs_read, /* 6 */
- call_nfs_writecache, /* 7 */
- call_nfs_write, /* 8 */
- call_nfs_create, /* 9 */
- call_nfs_remove, /* 10 */
- call_nfs_rename, /* 11 */
- call_nfs_link, /* 12 */
- call_nfs_symlink, /* 13 */
- call_nfs_mkdir, /* 14 */
- call_nfs_rmdir, /* 15 */
- call_nfs_readdir, /* 16 */
- call_nfs_statfs /* 17 */
- };
- int (*nfs_repl_proc[])() = {
- repl_nfs_null, /* 0 */
- repl_nfs_getattr, /* 1 */
- repl_nfs_setattr, /* 2 */
- repl_nfs_root, /* 3 */
- repl_nfs_lookup, /* 4 */
- repl_nfs_readlink, /* 5 */
- repl_nfs_read, /* 6 */
- repl_nfs_writecache, /* 7 */
- repl_nfs_write, /* 8 */
- repl_nfs_create, /* 9 */
- repl_nfs_remove, /* 10 */
- repl_nfs_rename, /* 11 */
- repl_nfs_link, /* 12 */
- repl_nfs_symlink, /* 13 */
- repl_nfs_mkdir, /* 14 */
- repl_nfs_rmdir, /* 15 */
- repl_nfs_readdir, /* 16 */
- repl_nfs_statfs /* 17 */
- };
-
- int (*nfs_emit_proc[])() = {
- emit_nfs_null, /* 0 */
- emit_nfs_getattr, /* 1 */
- emit_nfs_setattr, /* 2 */
- emit_nfs_root, /* 3 */
- emit_nfs_lookup, /* 4 */
- emit_nfs_readlink, /* 5 */
- emit_nfs_read, /* 6 */
- emit_nfs_writecache, /* 7 */
- emit_nfs_write, /* 8 */
- emit_nfs_create, /* 9 */
- emit_nfs_remove, /* 10 */
- emit_nfs_rename, /* 11 */
- emit_nfs_link, /* 12 */
- emit_nfs_symlink, /* 13 */
- emit_nfs_mkdir, /* 14 */
- emit_nfs_rmdir, /* 15 */
- emit_nfs_readdir, /* 16 */
- emit_nfs_statfs /* 17 */
- };
-
-
- char *nfs_proc_name[] = {
- "null",
- "getattr",
- "setattr",
- "root",
- "lookup",
- "readlink",
- "read",
- "writecache",
- "write",
- "creat",
- "remove",
- "rename",
- "link",
- "symlink",
- "mkdir",
- "rmdir",
- "readdir",
- "statfs"
- };
-
- char *stat_name[] = {
- "ok", /* 0 */
- };
-
-
- /* data structure for nfs transaction (both call and reply) */
- typedef struct nfstrans {
- char src[64], dst[64]; /* with respect to the CALL */
- u_long s, d; /* in versions of src & dest */
- u_long xid; /* xid + s + d is a unique identifier */
- u_int uid;
- u_long timestamp; /* arrival time of the CALL */
- int ser; /* ditto */
- long proc; /* what procedure - tag for union */
- union { /* call/reply struct for each proc */
- struct { /* nfs_null*/
- int call; /* no args*/
- int repl;
- } null;
- struct { /* nfs_getattr */
- fhandle_t call;
- struct nfsattrstat reply;
- } getattr;
- struct { /* nfs_setattr */
- struct nfssaargs call;
- struct nfsattrstat reply;
- } setattr;
- struct { /* nfs_root */
- int call;
- int reply;
- } root; /* should never get this one */
- struct { /* nfs_lookup */
- struct nfsdiropargs call;
- struct nfsdiropres reply;
- } lookup;
- struct { /* nfs_readlink */
- fhandle_t call;
- struct nfsrdlnres reply;
- } readlink;
- struct { /* nfs_read */
- struct nfsreadargs call;
- struct nfsrdresult reply; /* we ignore data */
- } read;
- struct { /* nfs_writecache */
- int call;
- int result;
- } writecache; /* should also never get this */
- struct { /* nfs_write */
- struct nfswriteargs call;
- struct nfsattrstat reply;
- } write;
- struct { /* nfs_create */
- struct nfscreatargs call;
- struct nfsdiropres reply;
- } create;
- struct { /* nfs_remove */
- struct nfsdiropargs call;
- enum nfsstat reply;
- } remove;
- struct { /* nfs_rename */
- struct nfsrnmargs call;
- enum nfsstat reply;
- } rename;
- struct { /* nfs_link */
- struct nfslinkargs call;
- enum nfsstat reply;
- } link;
- struct { /* nfs_symlink */
- struct nfsslargs call;
- enum nfsstat reply;
- } symlink;
- struct { /* nfs_mkdir */
- struct nfscreatargs call;
- struct nfsdiropres reply;
- } mkdir;
- struct { /* nfs_rmdir */
- struct nfsdiropargs call;
- enum nfsstat reply;
- } rmdir;
- struct { /* nfs_readdir */
- struct nfsrddirargs call;
- struct nfsrddirres reply;
- } readdir;
- struct { /* nfs_statfs */
- fhandle_t call;
- struct nfsstatfs reply;
- } statfs;
- } args;
- /* some data blocks so we can just malloc and free once */
- char b1[NFS_MAXPATHLEN];
- char b2[NFS_MAXPATHLEN];
- char b3[NFS_MAXNAMLEN];
- char b4[NFS_MAXNAMLEN];
- char b5[1024]; /* for whatever */
- struct nfstrans *next;
- } nfstrans;
-
- #define QSIZE 257
- static nfstrans *transqueue[QSIZE]; /* hash table of trans queue entries */
-
- #define MAXAGE 3 /* nuke any call over MAXAGE secs old */
- #define MAXTRANS 1000
-
- typedef struct hostrec {
- char name[64];
- u_long addr;
- int handlen; /* or 0 for generic */
- struct hostrec *next;
- } hostcache_t;
-
- hostcache_t *hostcache[QSIZE];
-
- extern long secs; /* current time in secs */
- extern int ser; /* packets this second */
-
- int defaultsize=0;
- int size=0; /* set before call to emit - used by phandle */
-
- int good=0;
- int bad=0;
-
- int ok=0; notok=0; call=0;
- int ngc=0, fgc=0;
- int nt=0;
- int lastgc=0;
- int terseflag=0;
-
- char *nuke[64]="Princeton.EDU";
- char *host();
-
- /*
- * This has the command line processing, the setup code, and the main loop.
- */
- main(argc,argv)
- int argc;
- char **argv;
- {
- int efd;
- ether_packet pkt;
- long pb[MTU/sizeof(long)];
- int len;
- int i;
- static char interface[32]=DEFAULT;
- char *flag;
- char *pn;
- char *c;
- int runtime;
-
- pn=argv[0];
- while (--argc) {
- if (**++argv == '-') { /* flag */
- for (flag = ++*argv; *flag; flag++) {
- switch (*flag) {
- case 'c': /* concise output */
- terseflag++;
- break;
- case 'h': /* handle size */
- case 'i': /* interface */
- case 't': /* run time */
- case 's': /* suf. to nuke */
- enq(*flag);
- break;
- default:
- usage(pn);
- exit(-1);
- }
- }
- } else {
- switch (deq()) {
- case -1:
- usage(pn);
- exit(-1);
- case 'h': /* handle size */
- if ((c=index(*argv,':')) == NULL) {
- if(sscanf(*argv,"%d",&defaultsize)!=1) {
- usage(pn);
- exit(-1);
- }
- } else {
- *c++='\0';
- if (sscanf(c,"%d",&size)!=1) {
- usage(pn);
- exit(-1);
- }
- addsize(*argv,size);
- }
- break;
- case 'i': /* interface */
- strcpy(interface,*argv);
- break;
- case 't': /* run time */
- runtime=atoi(*argv);
- if (runtime) {
- signal(SIGALRM,die);
- alarm(runtime);
- } else {
- usage(pn);
- exit(-1);
- }
- break;
- case 's': /* nuke */
- strcpy(nuke,*argv);
- break;
- default: /* should never happen */
- fprintf(stderr,"Internal error\n");
- exit(-2);
- }
- }
-
- }
- if ((deq() != -1)) {
- usage(pn);
- exit(-1);
- }
- for (i=0; i<QSIZE; i++) {
- transqueue[i]=NULL;
- hostcache[i]=NULL;
- }
- if ((efd=net_open(interface)) <0) {
- perror(interface);
- exit(1);
- }
- sethostent(1);
-
- /*
- * MAIN LOOP
- */
- while(1) {
- if ((len=net_read(efd,&pkt,MTU))<0) {
- perror("net_read");
- #ifdef NIT
- exit(-1);
- #else
- /* this is to fix a sporatic ultrix bug */
- printf("# net_read returned <0!\n");
- close(efd);
- fflush(stdout);
- if ((efd=net_open(interface))<0)
- exit(1);
- continue;
- #endif
- }
- bcopy(pkt.data,pb,len);
- if (do_inet(pb,len-14))
- good++;
- else
- bad++;
- ser++;
- if ((nt>MAXTRANS) && ((secs-lastgc)> MAXAGE))
- gc();
- }
- }
-
- usage(s)
- char *s;
- {
- fprintf(stderr,"usage: %s [-t runtime] [-h <handlesize]\n", s);
- fprintf (stderr," [-h host:handle] [-i interface] [-s suf] [-c]\n");
- }
-
-
- #define QS 10
- struct {
- int data[QS];
- int head;
- int tail;
- } argq = {{0},0,0};
-
- enq(f)
- char f;
- {
- argq.tail++;
- argq.tail %= QS;
- if (argq.head==argq.tail) {
- fprintf(stderr,"Can't deal with this\n");
- exit(-2);
- }
- argq.data[argq.tail]=f;
- }
-
- deq()
- {
- if (argq.head==argq.tail)
- return -1;
- argq.head++;
- argq.head %= QS;
- return(argq.data[argq.head]);
- }
-
- typedef struct sizelist {
- char name[64];
- int size;
- struct sizelist *next;
- } sizelist;
-
- sizelist *firstsize=NULL;
-
- /* add to handle size list.
- * should check for duplicates.
- * should really be a hash table.
- */
- addsize(h,s)
- char *h;
- int s;
- {
- sizelist *sl;
-
- if ((sl=(sizelist *)malloc(sizeof (sizelist))) == NULL) {
- fprintf(stderr,"Give up! can't even malloc handle record\n");
- exit(-2);
- }
- strcpy(sl->name,h);
- sl->size=s;
- sl->next=firstsize;
- firstsize=sl;
- }
-
- /* look up host- return default size if not found */
- hsize(h)
- char *h;
- {
- sizelist *sl;
- sl=firstsize;
- while (sl!=NULL) {
- if (strcmp(h,sl->name)==0)
- return sl->size;
- sl=sl->next;
- }
- return defaultsize;
- }
-
-
-
- do_inet(buf,len)
- char *buf;
- int len;
- {
- struct ip *pkt;
- int hl, plen;
- int offset;
- int proto;
- char *data;
-
- pkt=(struct ip *)buf;
- /* first make sure we have enough of the packet to deal with */
- if (len<sizeof(struct ip))
- return 0;
- hl = pkt->ip_hl*4;
- plen = ntohs(pkt->ip_len);
- if ((len<hl) || ((plen-hl>=8)&&(len<hl+8)))
- return 0;
- offset = htons(pkt->ip_off) & ~IP_DF & ~IP_MF;
- if (offset != 0)
- return 0; /* make sure it's the first fragment */
-
- proto = pkt->ip_p;
-
- data=(char *)pkt + hl;
- switch (proto) {
- case IPPROTO_UDP: /* UDP, which is all we know how to deal w/ */
- return(udp(&pkt->ip_src,&pkt->ip_dst,data,len-hl));
- break;
- default:
- return 0;
- }
- return 0;
- }
-
-
- /*
- * deal with udp packet
- */
- udp(s,d,pkt,len)
- struct in_addr *s, *d; /* yes, really */
- char *pkt;
- int len;
- {
- char src[255], dst[255];
- struct hostent *n;
- struct udphdr *u;
- struct rpc_msg *r;
- int direction;
-
- /* first, figure out whether its an nfs packet */
- u=(struct udphdr *)pkt;
- r=(struct rpc_msg *) ((char *)pkt+sizeof(struct udphdr));
-
- /*
- * first make sure it's an nfs packet (or whatever else we deal w/).
- * we make the unwholesome assumption that everybody uses NFS_PORT
- * as the nfs port. this is probably always true (i think).
- * should probably fix this to allow it to be specified at runtime
- * for each server, tho.
- * do some simple sanity checks on the packet first
- */
- direction=ntohl(r->rm_direction); /* this is cheating */
- if (ntohs(u->uh_sport) == NFS_PORT) {
- if (direction != REPLY)
- return 0; /* bad packet */
- } else if (ntohs(u->uh_dport) == NFS_PORT) {
- if (direction != CALL)
- return 0; /* bad packet */
- } else return 0; /* insert code for other services here */
-
- strcpy(src,host(s));
- strcpy(dst,host(d));
- return (nfs(src,dst,*(int*)s,*(int*)d,r,len-sizeof(struct udphdr)));
- }
-
-
- /*
- * host name lookup
- */
- char *host(h)
- struct in_addr *h;
- {
- hostcache_t *cache;
- struct hostent *hr;
- u_long bucket;
- unsigned char *c;
-
- bucket=h->s_addr%QSIZE;
- cache= hostcache[bucket];
- while (cache != NULL) {
- if (cache->addr = h->s_addr)
- return (cache->name);
- cache=cache->next;
- }
- if ((cache = (hostcache_t *)malloc(sizeof(hostcache_t))) == NULL) {
- fprintf(stderr,"No memory for host cache!\n");
- die();
- }
- if ((hr=gethostbyaddr(h,sizeof(u_long),AF_INET)) == NULL) {
- c=(unsigned char*)h;
- sprintf(cache->name,"%d.%d.%d.%d",c[0],c[1],c[2],c[3]);
- } else {
- strcpy(cache->name,hr->h_name);
- eliminate(cache->name,nuke);
- }
- cache->addr = h->s_addr;
- cache->next = hostcache[bucket];
- hostcache[bucket] = cache;
- return(cache->name);
- }
-
- eliminate(s1,s2)
- char *s1, *s2;
- {
- if ((*s1 == '\0') || (*s2=='\0'))
- return;
- while (*++s1)
- if (strcmp(s1,s2)==0) {
- *--s1='\0';
- return;
- }
- }
-
-
- /*
- * deal with rpc/nfs packet
- */
- nfs(src,dst,s,d,b,len)
- char *src;
- char *dst;
- u_long s; /* we know these are really u_long */
- u_long d; /* should be in_addr */
- struct rpc_msg *b;
- int len;
- {
- static struct rpc_msg rb;
- static struct rpc_msg *r = &rb;
- u_int uid;
- XDR xs;
- int stat=0;
- static char x[MAX_AUTH_BYTES]; /* we should fix this. */
-
- /* first, unxdr the rpc message header */
- xdrmem_create(&xs,b,len,XDR_DECODE); /* create the stream */
-
- switch (ntohl(b->rm_direction)) { /* we have to peek first */
- case CALL: /* it's a call, so we have to queue it */
- /* un xdr it */
- r->rm_call.cb_cred.oa_base=x;
- if (!xdr_mycallmsg(&xs,r)) { /* the library one just sucks */
- printf ("#CALL: bad\n");
- break;
- }
- /* first, be sure it's really nfs */
- if (r->rm_call.cb_prog != NFS_PROGRAM) {
- fprintf(stderr," Non-NFS program on NFS_PORT\n");
- break;
- }
- /* extract auth info */
- uid = -1; /* default */
- if (r->rm_call.cb_cred.oa_flavor == AUTH_UNIX) {
- XDR xx;
- xdrmem_create(&xx,x,r->rm_call.cb_cred.oa_length,
- XDR_DECODE);
- xdr_uid(&xx,&uid);
- xdr_destroy(&xx);
- }
- stat = nfscall(src,dst,s,d,uid,&xs,
- r->rm_xid,r->rm_call.cb_proc);
- break;
- case REPLY:
- if (!xdr_myreplymsg(&xs,r)) { /* the library one also sucks */
- printf("#REPL: bad\n");
- break;
- }
- stat = nfsreply(src,dst,s,d,&xs,
- r->rm_xid,r->rm_reply.rp_stat,
- r->acpted_rply.ar_stat);
- /* ar_stat contains garbage if it wasn't */
- /* really accepted, but we never look @ it */
- break;
- default:
- printf ("#bad direction\n");
- }
- xdr_destroy(&xs);
- return stat;
- }
-
-
-
-
-
- nfscall(src,dst,s,d,uid,arg,xid,proc)
- char *src;
- char *dst;
- u_long s,d;
- u_int uid;
- XDR *arg;
- u_long xid;
- long proc;
- {
- nfstrans *t;
- u_long hashval;
-
- /* first make sure it's a reasonable proc # */
- if ((proc<0) || !(proc<RFS_NPROC))
- return 0;
-
- if ((t=(nfstrans *)malloc(sizeof(nfstrans))) == NULL) {
- gc();
- /* try again */
- if((t=(nfstrans *)malloc(sizeof(nfstrans))) == NULL) {
- fprintf(stderr,"Damn, out of memory\n");
- printf("#out transaction memory\n");
- die();
- }
- }
- if ( (*nfs_call_proc[proc])(arg,t)) {
- /* init the transaction and stick it in place on the queue */
- t->s = s;
- t->d = d;
- t->xid=xid;
- t->uid=uid;
- strcpy(t->src,src);
- strcpy(t->dst,dst);
- t->proc = proc;
- t->timestamp = secs;
- t->ser = ser;
- hashval = xid%QSIZE;
- if (hashval>QSIZE) {
- fprintf(stderr,"%u!!!\n",hashval);
- die();
- }
- t->next = transqueue[hashval];
- transqueue[hashval] = t;
- call++;
- nt++;
- return 1;
- } else {
- free(t);
- return 0;
- }
- }
-
- nfstrans *findanddq();
-
-
- nfsreply(src,dst,s,d,arg,xid,stat,astat)
- char *src;
- char *dst;
- u_long s,d;
- XDR *arg;
- long xid;
- long stat;
- long astat;
- {
- nfstrans *t;
-
- if ((t=findanddq(s,d,xid)) == NULL) {
- notok++;
- return 0;
- }
- if ((stat!=0)||(astat!=0) || ((*nfs_repl_proc[t->proc])(arg,t) == 0)) {
- ok++;
- nt--;
- free (t);
- return 0;
- }
- size=hsize(t->dst); /* zero = unknown size */
- emit (t);
- nt--;
- free (t);
- ok++;
- return 1;
- }
-
-
-
- nfstrans *findanddq(s,d,xid)
- u_long s,d,xid;
- {
- nfstrans *t;
- nfstrans *tt;
- nfstrans **ptr;
- u_long hashval;
-
- hashval = xid%QSIZE;
- t=transqueue[hashval];
- ptr = &transqueue[hashval];
- while (t != NULL) {
- if ((t->xid == xid) && (t->s == d) && (t->d == s)) {
- *ptr = t->next;
- return t;
- }
- /* quick gc test */
- if ((secs - t->timestamp) > MAXAGE) {
- fgc++;
- *ptr = t->next;
- tt=t;
- t=t->next;
- nt--;
- free (tt);
- }
- else {
- ptr = &t->next;
- t=t->next;
- }
- }
- return NULL;
- }
-
-
- gc()
- {
- static int i;
- static nfstrans *t, **ptr, *tt;
-
- ngc++;
- printf("# garbage collecting %d\n",nt);
- for (i=0; i<QSIZE; i++) {
- t=transqueue[i];
- ptr = &transqueue[i];
- while (t!=NULL)
- if ((secs-t->timestamp)>MAXAGE) {
- *ptr = t->next;
- tt=t;
- t=t->next;
- nt--;
- free (tt);
- } else {
- ptr = &t->next;
- t=t->next;
- }
- }
- lastgc=secs;
- printf("#done %d\n",nt);
- }
-
- emit(t)
- nfstrans *t;
- {
- printf("%d.%06d | %s | %s.%d | %s | ",
- secs,ser,t->dst,t->src,t->uid,nfs_proc_name[t->proc]);
- if (!terseflag)
- (*nfs_emit_proc[t->proc])(t);
- printf("\n");
- }
-
-
- /*
- * functions for the various nfs procedures
- */
-
-
- /* NFS_CALL */
-
- call_nfs_null(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- /* this one's easy; no xdr data */
- return 1;
- }
-
- repl_nfs_null(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return 1;
- }
-
- emit_nfs_null(t)
- nfstrans *t;
- {
- printf("|");
- }
-
-
- /* NFS_GETATTR */
-
- call_nfs_getattr(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_fhandle(xs,&t->args.getattr.call));
- }
-
- repl_nfs_getattr(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_attrstat(xs,&t->args.getattr.reply));
- }
-
- emit_nfs_getattr(t)
- nfstrans *t;
- {
- fhandle_t *call;
- struct nfsattrstat *reply;
-
- call = &t->args.getattr.call;
- reply= &t->args.getattr.reply;
- phandle(call);
- printf("| %s",reply->ns_status?"failed":"ok");
- if (reply->ns_status == NFS_OK) {
- printf(", ");
- printfattr(&reply->ns_attr);
- }
- }
-
- /* NFS_SETATTR */
-
- call_nfs_setattr(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_saargs(xs,&t->args.setattr.call));
- }
-
- repl_nfs_setattr(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_attrstat(xs,&t->args.setattr.reply));
- }
-
- emit_nfs_setattr(t)
- nfstrans *t;
- {
- struct nfssaargs *call;
- struct nfsattrstat *reply;
-
- call = &t->args.setattr.call;
- reply= &t->args.setattr.reply;
- printf("{");
- phandle(&call->saa_fh);
- printf(", ");
- printsattr(&call->saa_sa);
- printf("} | %s",reply->ns_status?"failed":"ok");
- if (reply->ns_status == NFS_OK) {
- printf(", ");
- printfattr(&reply->ns_attr);
- }
- }
-
- /* NFS_ROOT */
-
- call_nfs_root(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return 1;
- }
-
- repl_nfs_root(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return 1;
- }
-
- emit_nfs_root(t)
- nfstrans *t;
- {
- printf("|");
- }
-
- /* NFS_LOOKUP */
-
- call_nfs_lookup(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- /* ok, this one's a bit tricky, because we have to set up pointers */
- t->args.lookup.call.da_name = t->b1;
- return(xdr_diropargs(xs,&t->args.lookup.call));
- }
-
- repl_nfs_lookup(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_diropres(xs,&t->args.lookup.reply));
- }
-
- emit_nfs_lookup(t)
- nfstrans *t;
- {
- struct nfsdiropargs *call;
- struct nfsdiropres *reply;
-
- call = &t->args.lookup.call;
- reply= &t->args.lookup.reply;
- printdiropargs(call);
- printf(" | %s",reply->dr_status?"failed":"ok");
- if (reply->dr_status == NFS_OK) {
- printf(", ");
- printdiropres(reply);
- }
- }
-
- /* NFS_READLINK */
-
- call_nfs_readlink(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_fhandle(xs,&t->args.readlink.call));
- }
-
- repl_nfs_readlink(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- t->args.readlink.reply.rl_data = t->b1;
- return(xdr_rdlnres(xs,&t->args.readlink.reply));
- }
-
- emit_nfs_readlink(t)
- nfstrans *t;
- {
- fhandle_t *call;
- struct nfsrdlnres *reply;
-
- call = &t->args.readlink.call;
- reply= &t->args.readlink.reply;
- phandle(call);
- printf("| %s",reply->rl_status?"failed":"ok");
- if (reply->rl_status == NFS_OK) {
- printf(", ");
- reply->rl_data[reply->rl_count] = '\0';
- printstr(reply->rl_data);
- }
- }
-
- /* NFS_READ */
-
- call_nfs_read(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_readargs(xs,&t->args.read.call));
- }
-
- repl_nfs_read(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- static char buf[MTU]; /* garbage place to store data */
-
- t->args.read.reply.rr_data = buf;
- return(xdr_rdresult(xs,&t->args.read.reply));
- }
-
- emit_nfs_read(t)
- nfstrans *t;
- {
- struct nfsreadargs *call;
- struct nfsrdresult *reply;
-
- call = &t->args.read.call;
- reply= &t->args.read.reply;
- printf("{");
- phandle(&call->ra_fhandle);
- printf(", %d, %d} |",
- call->ra_offset,
- call->ra_count);
- printf(" %s",reply->rr_status?"failed":"ok");
- if (reply->rr_status == NFS_OK) {
- printf(", %d",reply->rr_count);
- }
- }
-
- /* NFS_WRITECACHE */
-
- call_nfs_writecache(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return 1;
- }
-
- repl_nfs_writecache(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return 1;
- }
-
- emit_nfs_writecache(t)
- nfstrans *t;
- {
- printf("|");
- }
-
- /* NFS_WRITE */
-
- call_nfs_write(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- static char buf[MTU]; /* another garbage place */
-
- t->args.write.call.wa_data = buf;
- return(xdr_writeargs(xs,&t->args.write.call));
- }
-
- repl_nfs_write(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_attrstat(xs,&t->args.write.reply));
- }
-
- emit_nfs_write(t)
- nfstrans *t;
- {
- struct nfswriteargs *call;
- struct nfsattrstat *reply;
-
- call = &t->args.write.call;
- reply= &t->args.write.reply;
- printf("{");
- phandle(&call->wa_fhandle);
- printf(", %d, %d} |",
- call->wa_offset,
- call->wa_count);
- printf(" %s",reply->ns_status?"failed":"ok");
- if (reply->ns_status == NFS_OK) {
- printf(", ");
- printfattr(&reply->ns_attr);
- }
- }
-
- /* NFS_CREATE */
-
- call_nfs_create(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- t->args.create.call.ca_da.da_name = t->b3;
- return(xdr_creatargs(xs,&t->args.create.call));
- }
-
- repl_nfs_create(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_diropres(xs,&t->args.create.reply));
- }
-
- emit_nfs_create(t)
- nfstrans *t;
- {
- struct nfscreatargs *call;
- struct nfsdiropres *reply;
-
- call = &t->args.create.call;
- reply= &t->args.create.reply;
- printf("{");
- phandle(&call->ca_da.da_fhandle);
- printf(", ");
- printstr(call->ca_da.da_name);
- printf(", ");
- printsattr(&call->ca_sa);
- printf("} | %s",reply->dr_status?"failed":"ok");
- if (reply->dr_status == NFS_OK) {
- printf(", {");
- phandle(&reply->dr_fhandle);
- printf(", ");
- printfattr(&reply->dr_attr);
- printf("}");
- }
- }
-
- /* NFS_REMOVE */
-
- call_nfs_remove(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- t->args.remove.call.da_name = t->b3;
- return(xdr_diropargs(xs,&t->args.remove.call));
- }
-
- repl_nfs_remove(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_enum(xs,&t->args.remove.reply));
- }
-
-
- emit_nfs_remove(t)
- nfstrans *t;
- {
- struct nfsdiropargs *call;
- enum nfsstat *reply;
-
- call = &t->args.remove.call;
- reply= &t->args.remove.reply;
- printdiropargs(call);
- printf(" | %s", *reply?"failed":"ok");
- }
-
- /* NFS_RENAME */
-
- call_nfs_rename(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- t->args.rename.call.rna_from.da_name = t->b3;
- t->args.rename.call.rna_to.da_name = t->b4;
- return(xdr_rnmargs(xs,&t->args.rename.call));
- }
-
- repl_nfs_rename(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_enum(xs,&t->args.rename.reply));
- }
-
-
- emit_nfs_rename(t)
- nfstrans *t;
- {
- struct nfsrnmargs *call;
- enum nfsstat *reply;
-
- call = &t->args.rename.call;
- reply= &t->args.rename.reply;
- printdiropargs(&call->rna_from);
- printf(", ");
- printdiropargs(&call->rna_to);
- printf(" | %s",*reply?"failed":"ok");
- }
-
- /* NFS_LINK */
-
- call_nfs_link(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- t->args.link.call.la_to.da_name = t->b3;
- return(xdr_linkargs(xs,&t->args.link.call));
- }
-
- repl_nfs_link(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_enum(xs,&t->args.link.reply));
- }
-
- emit_nfs_link(t)
- nfstrans *t;
- {
- struct nfslinkargs *call;
- enum nfsstat *reply;
-
- call = &t->args.link.call;
- reply= &t->args.link.reply;
- printf("{");
- phandle(&call->la_from);
- printf(", ");
- printdiropargs(&call->la_to);
- printf("} | %s",*reply?"failed":"ok");
- }
-
- /* NFS_SYMLINK */
-
- call_nfs_symlink(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- t->args.symlink.call.sla_from.da_name = t->b3;
- t->args.symlink.call.sla_tnm = t->b1;
- return(xdr_slargs(xs,&t->args.symlink.call));
- }
-
- repl_nfs_symlink(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_enum(xs,&t->args.symlink.reply));
- }
-
-
- emit_nfs_symlink(t)
- nfstrans *t;
- {
- struct nfsslargs *call;
- enum nfsstat *reply;
-
- call = &t->args.symlink.call;
- reply= &t->args.symlink.reply;
- printf("{");
- printdiropargs(&call->sla_from);
- printf(", ");
- printstr(call->sla_tnm);
- printf(", ");
- printsattr(&call->sla_sa);
- printf("} | %s",*reply?"failed":"ok");
- }
-
- /* NFS_MKDIR */
-
- call_nfs_mkdir(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- t->args.mkdir.call.ca_da.da_name = t->b3;
- return(xdr_creatargs(xs,&t->args.mkdir.call));
- }
-
- repl_nfs_mkdir(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_diropres(xs,&t->args.mkdir.reply));
- }
-
- emit_nfs_mkdir(t)
- nfstrans *t;
- {
- struct nfscreatargs *call;
- struct nfsdiropres *reply;
-
- call = &t->args.mkdir.call;
- reply= &t->args.mkdir.reply;
- printf("{");
- phandle(&call->ca_da.da_fhandle);
- printf(", ");
- printstr(call->ca_da.da_name);
- printf(", ");
- printsattr(&call->ca_sa);
- printf("} | %s",reply->dr_status?"failed":"ok");
- if (reply->dr_status == NFS_OK) {
- printf(", {");
- phandle(&reply->dr_fhandle);
- printf(", ");
- printfattr(&reply->dr_attr);
- printf("}");
- }
- }
-
- /* NFS_RMDIR */
-
- call_nfs_rmdir(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- t->args.rmdir.call.da_name = t->b3;
- return(xdr_diropargs(xs,&t->args.rmdir.call));
- }
-
- repl_nfs_rmdir(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_enum(xs,&t->args.rmdir.reply));
- }
-
- emit_nfs_rmdir(t)
- nfstrans *t;
- {
- struct nfsdiropargs *call;
- enum nfsstat *reply;
-
- call = &t->args.rmdir.call;
- reply= &t->args.rmdir.reply;
- printdiropargs(call);
- printf(" | %s",*reply?"failed":"ok");
- }
-
- /* NFS_READDIR */
-
- call_nfs_readdir(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_rddirargs(xs,&t->args.readdir.call));
- }
-
- repl_nfs_readdir(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- t->args.readdir.reply.rd_entries = NULL; /* we dont use */
- return(xdr_getrddirres(xs,&t->args.readdir.reply));
- }
-
- emit_nfs_readdir(t)
- nfstrans *t;
- {
- fhandle_t *call;
- struct nfsattrstat *reply;
-
- phandle(&t->args.readdir.call.rda_fh);
- printf(" | %s",t->args.readdir.reply.rd_status?"failed":"ok");
-
- }
-
- /* NFS_STATFS */
-
- call_nfs_statfs(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_fhandle(xs,&t->args.statfs.call));
- }
-
- repl_nfs_statfs(xs,t)
- XDR *xs;
- nfstrans *t;
- {
- return(xdr_statfs(xs,&t->args.readdir.reply));
- }
-
- emit_nfs_statfs(t)
- nfstrans *t;
- {
- fhandle_t *call;
- struct nfsattrstat *reply;
-
- printf(" |");
- return 1;
- }
-
- #define HSIZE 14 /* max reasonable handle size for funny file handles */
- #define min(x,y) ((x)>(y)?(y):(x))
-
- phandle(h)
- fhandle_t *h;
- {
- u_long i;
- u_long j;
- u_char *p;
- unsigned char buf[64];
- int si;
-
- buf[0]='\0';
- j=min(h->fh_len,ntohs(h->fh_len));
- j-=4;
- si=size;
- if (si) {
- p=(u_char *)h;
- while(si--)
- sprintf(buf,"%s%02x",buf,*(p++));
- } else if (((j<0) || (j>FHMAXDATA)) || /* guess size */
- !(h->fh_fsid.val[0]+h->fh_fsid.val[1])) {/* funny (utrix/mach) */
- p = (u_char *) h;
- for (i=0; i<HSIZE; i++)
- sprintf(buf,"%s%02x",buf,p[i]);
- } else { /* regular kind */
- sprintf(buf,"%08x%08x",(h->fh_fsid.val[0]),
- (h->fh_fsid.val[1]));
- for(i=0;i<j; i++)
- sprintf(buf,"%s%02x",buf,(unsigned char)h->fh_data[i]);
- }
- p=buf;
- while (*p && (*p=='0'))
- p++;
- printf("\"%s\"",p);
- }
-
-
- /*
- * XDR routines
- */
-
-
- xdr_uid(xs,u)
- XDR *xs;
- u_int *u;
- {
- static char junk[255];
- u_int stamp;
- return (xdr_int(xs,&stamp) && xdr_string(xs,junk,255)
- && xdr_u_int(xs,u));
- }
-
-
- xdr_myreplymsg(xs,r)
- XDR *xs;
- struct rpc_msg *r;
- {
- static char x[MAX_AUTH_BYTES];
-
- if (xdr_u_long(xs, &(r->rm_xid)) &&
- xdr_enum(xs, &(r->rm_direction)) &&
- (r->rm_direction==REPLY) &&
- xdr_enum(xs, &(r->rm_reply.rp_stat)) &&
- (r->rm_reply.rp_stat==MSG_ACCEPTED) && /* ignore if rejected */
- ((r->acpted_rply.ar_verf.oa_base=x),1) && /* this is disgusting */
- xdr_opaque_auth(xs, &(r->acpted_rply.ar_verf)))
- return (xdr_enum(xs, &(r->acpted_rply.ar_stat)));
- return (FALSE);
- /* note that we now point to the begining of the reply data */
- }
-
- xdr_mycallmsg(xs,r)
- XDR *xs;
- struct rpc_msg *r;
- {
- static char x[MAX_AUTH_BYTES]; /* stupid ugly hack */
-
- if (xdr_u_long(xs, &(r->rm_xid)) &&
- xdr_enum(xs, &(r->rm_direction)) &&
- (r->rm_direction == CALL) &&
- xdr_u_long(xs, &(r->rm_call.cb_rpcvers)) &&
- (r->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
- xdr_u_long(xs, &(r->rm_call.cb_prog)) &&
- xdr_u_long(xs, &(r->rm_call.cb_vers)) &&
- xdr_u_long(xs, &(r->rm_call.cb_proc)) &&
- /* ((r->rm_call.cb_cred.oa_base=x),1) && */
- xdr_opaque_auth(xs, &(r->rm_call.cb_cred))) {
- r->rm_call.cb_verf.oa_base=x;
- return (xdr_opaque_auth(xs, &(r->rm_call.cb_verf)));
- }
- return FALSE;
- }
-
-
- printdiropres(r)
- struct nfsdiropres *r;
- {
- printf("{");
- phandle(&r->dr_fhandle);
- printf(", ");
- printfattr(&r->dr_attr);
- printf("}");
- }
-
-
- printfattr(f)
- struct nfsfattr *f;
- {
- printf("{0%o, %d, %d, 0x%x}",
- f->na_mode,
- f->na_uid,
- f->na_size,
- f->na_nodeid);
- }
-
- printsattr(s)
- struct nfssattr *s;
- {
- printf("{0%o, %d, %d}",
- s->sa_mode,
- s->sa_uid,
- s->sa_size);
- }
-
-
- printdiropargs(d)
- struct nfsdiropargs *d;
- {
- printf("{");
- phandle(&d->da_fhandle);
- printf(", ");
- printstr(d->da_name);
- printf("}");
- }
-
- printstr(s)
- char *s;
- {
- putchar('\"');
- while (*s) {
- switch (*s) {
- case '\\':
- case '\n':
- case '\"':
- case '|':
- putchar('\\');
- default:
- putchar (*s);
- }
- ++s;
- }
- putchar('\"');
- }
-